package com.yuyou.fn.educational.service.impl;

import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.github.wens.mybatisplus.toolkit.IdWorker;
import com.github.wens.mybatisplus.toolkit.StringUtil;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.util.BeanUtils;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.common.util.Utils;
import com.yuyou.fn.educational.entity.*;
import com.yuyou.fn.educational.mapper.StudentMapper;
import com.yuyou.fn.educational.service.*;
import com.yuyou.fn.educational.vo.StudentDetailVo;
import com.yuyou.fn.educational.vo.StudentImportVo;
import com.yuyou.fn.educational.vo.StudentSaveOrUpdateVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author Terry
 *         Student 表数据服务层接口实现类
 */
@Service
public class StudentServiceImpl extends SuperServiceImpl<StudentMapper, Student, Long> implements IStudentService {


    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private IStudentGuardianService studentGuardianService;

    @Resource
    private IBaseGradeService baseGradeService;

    @Resource
    private IMemberStudentService memberStudentService;

    @Resource
    private IStudentRegService studentRegService ;

    private static final Logger log  = LoggerFactory.getLogger(ExternalRegDetailServiceImpl.class);
    /**
     * 查询符合条件的学生信息
     *
     * @return
     */
    public Page<Student> findStudentByKeyword(String keyword, int pageNo, int pageSize) {


        Example<Student> studentExample = Student.createExample();
        studentExample.orderBy("updateTime").desc();
        if (StringUtils.isNotEmpty(keyword)){
            keyword = keyword.trim();
            keyword =  keyword + "%" ;
            studentExample.or().andLike("name" , keyword );
            studentExample.or().andLike("phoneNo" , keyword );
            studentExample.or().andLike("studentNo" , keyword );
            studentExample.or().andLike("slavePhoneNo",keyword);
        }
        return findPageByExample(studentExample, pageNo, pageSize);
    }

    /**
     * 增加或更新学生信息
     *
     * @param studentSaveOrUpdateVo
     */
    @Transactional
    public Long saveOrUpdateStudent(StudentSaveOrUpdateVo studentSaveOrUpdateVo) {
        Student student = new Student();

        BeanUtils.copyProperties(student, studentSaveOrUpdateVo);
        if (studentSaveOrUpdateVo.getName()!=null){
            studentSaveOrUpdateVo.setName(studentSaveOrUpdateVo.getName().trim());
        }
        if (studentSaveOrUpdateVo.getPhoneNo()!=null){
            studentSaveOrUpdateVo.setPhoneNo(studentSaveOrUpdateVo.getPhoneNo().trim());
        }

        if (studentSaveOrUpdateVo.getGradeId() != null) {
            student.setGradeName(baseGradeService.findGradeNameById(student.getGradeId()));
        }

        if(student.getReferrerId() != null ){
            student.setReferrerName(findById(student.getReferrerId()).getName());
        }

        checkStudent(student);
        Boolean insertState=false;
        if (student.getStudentId() == null) {
            insertState=true;
            student.setStudentId(IdWorker.getId());
            student.setStudentNo(newStudentNo());
            student.setCreateTime(TimeUtils.now());
            student.setUpdateTime(TimeUtils.now());
        } else {
            student.setUpdateTime(TimeUtils.now());
        }
        String cid=null;
        try {
            String s = memberStudentService.changeOrNewStudentNew(student);
            if (!"-1".equals(s) && !"".equals(s)){
                //throw new BusException("更新或者新增学生失败，请检查是否与原有学员冲突");
                cid=s;
            }
        }catch (Exception e){

        }
        student.setCid(cid);
        if (insertState){
            this.insertSelective(student);
        }else {
            this.updateSelectiveById(student);
        }

        if (studentSaveOrUpdateVo.getGuardianList()!=null && !studentSaveOrUpdateVo.getGuardianList().isEmpty()){
            studentGuardianService.saveOrUpdateGuardian(student.getStudentId(), studentSaveOrUpdateVo.getGuardianList());
        }

        return student.getStudentId();
    }




    private void checkStudent(Student student) {
        if (student.getStudentId()==null && StringUtils.isEmpty(student.getPhoneNo()) || StringUtils.isEmpty(student.getPhoneNo()) ){
            throw new BusException("学生手机号码或者姓名不能为空");
        }
        Set<String> phoneSet=new HashSet<>(2);
        phoneSet.add(student.getPhoneNo());
        if (StringUtil.isNotEmpty(student.getSlavePhoneNo())){
            phoneSet.add(student.getSlavePhoneNo());
        }
        Example<Student> example = Student.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("name",student.getName());

        List<Student> studentList=findListByExample(example);
        for (Student check:studentList){
            if ((student.getStudentId() == null || !student.getStudentId().equals(check.getStudentId())) &&(
            phoneSet.contains(check.getPhoneNo()) || phoneSet.contains(check.getSlavePhoneNo()))
                    ){
                throw new BusException("学生信息已经存在,请根据姓名或者手机查询");
            }
        }

    }


    @Override
    public StudentDetailVo findStudentDetailByStudentId(Long studentId) {
        Student student = findById(studentId);
        List<StudentGuardian> guardianList = studentGuardianService.findGuardianByStudentId(studentId);
        StudentDetailVo studentDetailVo = new StudentDetailVo();
        studentDetailVo.setStudent(student);
        studentDetailVo.setGuardianList(guardianList);
        return studentDetailVo;
    }

    /**
     * 生成学生编号
     *
     * @return
     */
    public String newStudentNo() {
        Calendar now = Calendar.getInstance();
        int year = now.get(Calendar.YEAR);
        Long no = redisTemplate.opsForValue().increment("student_no", 1);
        return year + StringUtils.leftPad(String.valueOf(no), 6, "0");
    }

    @Override
    public Student findByNameAndPhone(String name ,String phoneNo ) {
        Example<Student> example = Student.createExample();
        example.createCriteria().andEqualTo("phoneNo",phoneNo).andEqualTo("name", name  );
        example.or().andEqualTo("slavePhoneNo",phoneNo).andEqualTo("name",name);
        Student one = findOneByExample(example);

        return one;
    }



    @Override
    public List<Student> findByPhone(String phone) {
        if (StringUtils.isEmpty(phone)){
            return Collections.EMPTY_LIST;
        }
        Example<Student> example = Student.createExample();
        example.or().andEqualTo("phoneNo",phone);
        example.or().andEqualTo("slavePhoneNo",phone);
        return findListByExample(example);
    }

    @Override
    public void updateRegClassAmount(List<Long> studentIds) {
        for(Long studentId  : studentIds ){
            Example<StudentReg> example = StudentReg.createExample();
            example.createCriteria().andEqualTo("studentId", studentId ).andEqualTo("regStatus" , 0 );
            long l = studentRegService.countByExample(example);
            Student update = new Student();
            update.setStudentId(studentId);
            update.setRegClassAmount((int) l);
            updateSelectiveById(update);
        }
    }




    public static SXSSFWorkbook student2excel(List<Student> studentList) {

        SXSSFWorkbook excel = new SXSSFWorkbook();
        SXSSFSheet sheet = excel.createSheet("student");
        SXSSFRow firstRow = sheet.createRow(0);
        String[] titles = new String[]{"学号", "姓名", "手机号码", "出生日期", "年级", "就读学校", "地区"};

        for (int i = 0; i < titles.length; i++) {
            firstRow.createCell(i).setCellValue(titles[i]);
        }
        for (int i = 0; i < studentList.size(); i++) {
            SXSSFRow row = sheet.createRow(i + 1);
            Student student = studentList.get(i);
            SXSSFCell cell = row.createCell(0);
            cell.setCellValue(student.getStudentNo());

            cell = row.createCell(1);
            cell.setCellValue(student.getName());

            cell = row.createCell(2);
            cell.setCellValue(student.getPhoneNo());

            cell = row.createCell(3);
            cell.setCellValue(student.getBirthday());

            cell = row.createCell(4);
            cell.setCellValue(student.getGradeName());

            cell = row.createCell(5);
            cell.setCellValue(student.getSchool());

            cell = row.createCell(6);
            cell.setCellValue(student.getAddress());

        }
        return excel;
    }

    @Override
    public List<Student> findByStudentNos(List<String> studentNos) {
        Example<Student> example = Student.createExample();
        example.createCriteria().andIn("studentNo",studentNos );
        return findListByExample(example);
    }

    @Override
    public Student findByStudentNo(String studentNo) {
        if (!StringUtil.isNotEmpty(studentNo)){
            return null;
        }
        Example<Student> example = Student.createExample();
        example.createCriteria().andEqualTo("studentNo",studentNo );
        return findOneByExample(example);
    }

    @Override
    public void importStudent(List<StudentImportVo> studentImportVoList, String from) {
        if (studentImportVoList==null || StringUtils.isEmpty(from)){
            return;
        }
        /*记录最大的学号，过滤名称手机号码相同的信息*/
        Map<String,Student> recordMap=new HashMap<>();


        for (StudentImportVo studentImportVo : studentImportVoList) {
            String key = studentImportVo.getStudentName() + "_" + studentImportVo.getPhone();
            try {
                Student haveStudent =   this.findByStudentNo(from + studentImportVo.getStudentNo());
                if (haveStudent != null) {
                    continue;
                }
                Student student = this.findByNameAndPhone(studentImportVo.getStudentName(),studentImportVo.getPhone());
                if (student != null) {
                    Student update = new Student();
                    update.setName(studentImportVo.getStudentName());
                    update.setStudentNo(from + studentImportVo.getStudentNo());
                    update.setPhoneNo(studentImportVo.getPhone());
                    if (StringUtils.isNotEmpty(studentImportVo.getBirthday())) {
                        update.setBirthday(Utils.parseDate(studentImportVo.getBirthday(), "yyyy-MM-dd"));
                    }
                    update.setSex(studentImportVo.getSex().equals("男") ? 1 : 2);
                    update.setUpdateTime(TimeUtils.now());
                    Example<Student> example = Student.createExample();
                    example.createCriteria().andEqualTo("name", studentImportVo.getStudentName()).andEqualTo("phoneNo", studentImportVo.getPhone());
                    this.updateSelectiveByExample(update, example);
                } else {
                    Student check = recordMap.get(key);
                    if (check == null || check.getStudentNo().compareTo(from + studentImportVo.getStudentNo()) < 0) {
                        Student insert = new Student();
                        insert.setName(studentImportVo.getStudentName());
                        insert.setStudentNo(from + studentImportVo.getStudentNo());
                        insert.setPhoneNo(studentImportVo.getPhone());
                        if (StringUtils.isNotEmpty(studentImportVo.getBirthday())) {
                            insert.setBirthday(Utils.parseDate(studentImportVo.getBirthday(), "yyyy-MM-dd"));
                        }
                        insert.setSex(studentImportVo.getSex().equals("男") ? 1 : 2);
                        insert.setCreateTime(TimeUtils.now());
                        insert.setUpdateTime(TimeUtils.now());
                        insert.setRegClassAmount(0);
                        //insertList.add(insert);
                        recordMap.put(key, insert);
                        this.insert(insert);
                    }
                }
            } catch (Exception e) {
                log.error("学生姓名为:" + studentImportVo.getStudentName() + "," + "手机号码为:" + studentImportVo.getPhone() + "的学生记录存储失败");
                System.out.println("学生姓名为:" + studentImportVo.getStudentName() + "," + "手机号码为:" + studentImportVo.getPhone() + "的学生记录存储失败");
            }
        }


    }

    @Override
    public Student findByCID(String cid) {
        Example<Student> example = Student.createExample();
        example.createCriteria().andEqualTo("cid",cid );
        return findOneByExample(example);
    }

    @Override
    public List<Student> findByCIDs(List<String> cids) {
        Example<Student> example = Student.createExample();
        example.createCriteria().andIn("cid",cids );
        return findListByExample(example);
    }

    @Override
    public void updateNameAndPhoneAndSlavePhoneByCid(String cid, String name, String phoneNo,String slavePhoneNo) {
        if (StringUtil.isNotEmpty(cid)){
            Example<Student> example = Student.createExample();
            example.createCriteria().andEqualTo("cid",cid );
            example.orderBy("createTime").desc();
            Student student=this.findOneByExample(example);
            if (student!=null){
                Student update=new Student();
                update.setStudentId(student.getStudentId());
                update.setName(name);
                update.setPhoneNo(phoneNo);
                update.setUpdateTime(TimeUtils.now());
                update.setSlavePhoneNo(slavePhoneNo);
                this.updateSelectiveById(update);
            }
        }
    }

    @Override
    public void mergeStudentByOriginAndTargetStudentId(long originStudentId, long targetStudentId,String cid) {
        Student originStudent=this.findById(originStudentId);
        Student targetStudent=this.findById(targetStudentId);

        this.deleteById(originStudentId);
        if (!StringUtil.isNotEmpty(targetStudent.getSlavePhoneNo())) {
            Student update = new Student();
            update.setSlavePhoneNo(originStudent.getPhoneNo());
            update.setUpdateTime(TimeUtils.now());
            update.setCid(cid);
            update.setStudentId(targetStudentId);
            this.updateSelectiveById(update);
        }
    }

    @Override
    public Student findByPhoneNo(String phoneNo) {
        Example<Student> example = Student.createExample();
        example.createCriteria().andEqualTo("phoneNo",phoneNo );
        Student student=this.findOneByExample(example);
        return student;
    }

    @Override
    public List<Student> findByStudentNamesAndPhonesOrSlavePhones(List<String> studentNames, List<String> phoneNos, List<String> slavePhoneNos) {
        if (Utils.isEmpty(studentNames)){
            return Collections.EMPTY_LIST;
        }
        Example<Student> example = Student.createExample();
        example.createCriteria().andIn("phoneNo",phoneNos).andIn("name", studentNames  );
        example.or().andIn("slavePhoneNo",slavePhoneNos).andIn("name",studentNames);
        List<Student> studentList = findListByExample(example);
        return studentList;
    }

    @Override
    public List<Student> findStudentBySameName(long studentId) {
        Student student=this.findById(studentId);

        Example<Student> example = Student.createExample();
        example.createCriteria().andEqualTo("name",student.getName() ).andNotEqualTo("studentId",studentId);
        return this.findListByExample(example);
    }
}